package genstream.dublin

import genstream._
import scaladuct._
import asm.JavaBean
import scala.reflect.BeanProperty
import java.util.{ArrayList, Collections, Date}

/**
 * Created by IntelliJ IDEA.
 * User: zslajchrt
 * Date: 17.4.11
 * Time: 17:58
 * To change this template use File | Settings | File Templates.
 */

@serializable
@SerialVersionUID(1L)
trait DublinCoreResourceExt {
  @BeanProperty var contributor: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var coverage: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var creator: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var date: Date = null
  @BeanProperty var description: String = null
  @BeanProperty var format: String = null
  @BeanProperty var identifier: String = null
  @BeanProperty var language: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var publisher: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var relation: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var rights: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var source: java.util.List[String] = new java.util.ArrayList[String]
  @BeanProperty var subject: String = null
  @BeanProperty var title: String = null
  @BeanProperty var resourceType: String = null

  def adopt(other: DublinCoreResourceExt) {
    contributor = new ArrayList[String](other.contributor)
    coverage = new ArrayList[String](other.coverage)
    creator = new ArrayList[String](other.creator)
    date = other.date
    description = other.description
    format = other.format
    identifier = other.identifier
    language = new ArrayList[String](other.language)
    publisher = new ArrayList[String](other.publisher)
    relation = new ArrayList[String](other.relation)
    rights = new ArrayList[String](other.rights)
    source = new ArrayList[String](other.source)
    subject = other.subject
    title = other.title
    resourceType = other.resourceType
  }
}

@serializable
@JavaBean
class DublinCoreResourceExtCookie extends DublinCoreResourceExt

@SerialVersionUID(1L)
class DublinCoreResourceExtConfigPage(pageName: String, decorated: ConfigPage[ServiceFactory[InputResource]])
  extends NamedConfigPage[ServiceFactory[InputResource]](pageName, classOf[DublinCoreResourceExtConfigPage]) {

  type Cookie = DublinCoreResourceExtCookie

  val getCookie = new DublinCoreResourceExtCookie

  def consume(cookie: Cookie): ConfigResult[ServiceFactory[InputResource]] = {
    NextPage(new DublinCoreResourceExtWrapperPage(decorated, cookie))
  }

}

class DublinCoreResourceExtWrapperPage(decorated: ConfigPage[ServiceFactory[InputResource]], dc: DublinCoreResourceExt)
  extends ConfigPageDecorator[ServiceFactory[InputResource]](decorated) {

  override def consume(cookie: Cookie): ConfigResult[ServiceFactory[InputResource]] = {
    val result: ConfigResult[ServiceFactory[InputResource]] = super.consume(cookie)
    result match {
      case NextPage(nextPage) => NextPage(new DublinCoreResourceExtWrapperPage(nextPage, dc))
      case NewStarter(starter) => {

        // decorate the result
        val resourceServiceFactory: ServiceFactory[InputResource] = starter.newInstance
        val decoratingServiceFact: ServiceFactory[InputResource] = new FunctionalServiceFactory({

          // decorate the resource
          val decoratedResource: InputResource = resourceServiceFactory.newInstance
          val decoratingResource: InputResource = new InputResourceDecorator(decoratedResource) {

            override def openIterator(context: StreamingContext) = {
              // decorate the iterator
              val decoratedIterator = super.openIterator(context)
              new InputStreamIteratorDecorator(decoratedIterator) {

                override def next() = {
                  val decoratedStreamHolder = super.next
                  val holder = new InputStreamHolderDecorator(decoratedStreamHolder) with DublinCoreResourceExt
                  holder.adopt(dc)
                  holder
                }

              }

            }
          }

          decoratingResource
        })

        NewStarter(new BasicStarter(decoratingServiceFact))
      }
    }
  }
}